/*
 *  rlocuswidget.cpp
 *  Perceel
 *
 *  Created by Nicola Gigante on 24/03/08.
 *  Copyright 2008 Nicola Gigante. All rights reserved.
 *
 */

#include "plotwidget.h"

PlotWidget::PlotWidget(QWidget *parent) : QWidget(parent),
										  m_origin(0,0),
										  x_scale(1),
										  y_scale(1),
										  m_dragging(false),
										  m_resizing(false),
										  initPlotDone(false),
										  m_firstPaint(true),
										  m_pointerMode(DragMode),
										  m_horizAxis(0),
										  m_vertAxis(0)
{
	connect(&resizeTimer, SIGNAL(timeout()), this, SLOT(resizingFinished()));
	this->setMouseTracking(true);
	this->setCursor(Qt::OpenHandCursor);
}

void PlotWidget::reset()
{
	m_firstPaint = true;
	invalidate();
}

void PlotWidget::setOrigin(const QPointF &o)
{
	m_origin = o;
	invalidate();
}

void PlotWidget::setScale(Real x, Real y)
{
	x_scale = x;
	y_scale = y;
	invalidate();
}

void PlotWidget::setHorizontalAxis(Real pos)
{
	m_horizAxis = pos;
}

void PlotWidget::setVerticalAxis(Real pos)
{
	m_vertAxis = pos;
}

void PlotWidget::drawAces(QPainter &painter)
{
	Q_UNUSED(painter);
	
	QPointF o = map(QPointF(m_vertAxis, m_horizAxis));
	
	painter.save();
	
	painter.setPen(QPen(Qt::black, 2));
	painter.drawLine(rect().topLeft().x(), o.y(), rect().bottomRight().x(), o.y());
	painter.drawLine(o.x(), rect().topLeft().y(), o.x(), rect().bottomRight().y());
	
	painter.restore();
}

Complex PlotWidget::unMap(QPointF p)
{
	QMatrix m;
	
	m.translate(m_origin.x(), m_origin.y());
	m.scale(xScale(), -yScale());
	
	QPointF c = m.inverted().map(p);
	
	return Complex(c.x(), c.y());
}

QPointF PlotWidget::map(QPointF p)
{
	QMatrix m;
	
	m.translate(m_origin.x(), m_origin.y());
	m.scale(xScale(), -yScale());
	
	return m.map(p);
}

QPoint PlotWidget::map(QPoint p)
{
	return map(p);
}

QPointF PlotWidget::map(Complex c)
{
	return map(QPointF(real(c), imag(c)));
}

void PlotWidget::invalidate()
{
	if(!rendering.isNull())
	{
		rendering = QImage();
		update();
	}
}

void PlotWidget::resizeEvent(QResizeEvent *)
{
	// Resizing is starting
	if(!m_resizing)
	{
		m_resizing = true;
		resizeTimer.stop();
		m_oldDrawPoint = m_drawPoint;
	}
	resizeTimer.setInterval(500);
	resizeTimer.setSingleShot(true);
	resizeTimer.start();
}

void PlotWidget::resizingFinished()
{
	m_resizing = false;
	m_origin -= m_oldDrawPoint - m_drawPoint;
	invalidate();
}

void PlotWidget::setPointerMode(PointerMode m)
{
	m_pointerMode = m;
	switch(m)
	{
		case DragMode:
			setCursor(Qt::OpenHandCursor);
			break;
		case PointMode:
			setCursor(Qt::ArrowCursor);
			break;
	}
}

void PlotWidget::mousePressEvent(QMouseEvent *event)
{
	if(m_pointerMode == DragMode)
	{
		m_dragging = true;
		setCursor(Qt::ClosedHandCursor);
		m_oldDrawPoint = m_drawPoint;
		m_dragDistance = m_drawPoint - event->pos();
	}
}

void PlotWidget::mouseReleaseEvent(QMouseEvent *)
{
	if(m_pointerMode == DragMode)
	{
		m_dragging = false;
		m_origin -= m_oldDrawPoint - m_drawPoint;
		setCursor(Qt::OpenHandCursor);
		invalidate();
	}
}

void PlotWidget::mouseMoveEvent(QMouseEvent *event)
{
	if(m_pointerMode == DragMode && m_dragging)
	{
		m_drawPoint = event->pos() + m_dragDistance;
	}else if(m_pointerMode == PointMode)
	{
		QMap<QString, QString> m;
		Complex c = unMap(event->pos());
		m.insert(tr("Position"), complexToString(c));
		m.unite(pixelDetails(event->pos()));
		emit detailsChanged(m);
	}
	update();
}

void PlotWidget::zoomIn()
{
	setScale(xScale() * 2, yScale() * 2);
}

void PlotWidget::zoomOut()
{
	setScale(xScale() / 2, yScale() / 2);
}


QImage PlotWidget::doRendering(bool alone)
{
	qApp->setOverrideCursor(Qt::WaitCursor);
	QImage img(size(), QImage::Format_RGB32);
	
	QPainter painter(&img);
	
	painter.setRenderHints(QPainter::Antialiasing);
	painter.fillRect(rect(), Qt::white);

	// Backgrounds ecc...
	
	if(!initPlotDone && !alone)
	{
		initPlot(painter);
		initPlotDone = true;
	}
	
	drawAces(painter);
	
	if(m_firstPaint && !alone)
	{
		guessScale();
		m_firstPaint = false;
	}
	
	// Prepare plot data
	painter.save();
	plot(painter);
	painter.restore();
	
	qApp->restoreOverrideCursor();
	
	return img;
}

void PlotWidget::paintEvent(QPaintEvent *)
{
	if(rendering.isNull())
		rendering = doRendering();
		
	if(!m_dragging)
		m_drawPoint = QPoint((width() - rendering.width()) / 2, (height() - rendering.height()) / 2);
		//m_drawPoint = QPoint();
	
	QPainter painter(this);
	painter.fillRect(rect(), Qt::white);

	painter.drawImage(m_drawPoint, rendering);
}


